Matplotlibでアニメーションを作成

概要

PythonのMatplotlibを使用してFig. 1. に示すようなアニメーションを出力することを目標とします.

テーマは高校物理で度々扱う球を斜方投射した放物運動の軌跡とします.

pcolormesh_shading

Fig. 1. 放物運動のアニメーション

初速$v_0$,角度$\theta$で斜めに投射された球の$x$,$y$座標は時間$t$の関数として式(1),(2)で算出できます.

\begin{align} x & = v_0 \cos{\theta} \cdot t \\ y & = v_0 \sin{\theta} \cdot t - \frac{1}{2}gt^2 \end{align}

Pythonコード

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation
from matplotlib import patches

必要なパッケージをimportします.

ArtistAnimationがアニメーションに必要な関数です.

ArtistAnimationの他に同じくMatplotlibのFuncAnimationという関数を使ってアニメーションを作成する方法もありますが,ArtistAnimationの方が直感的に使えるため今回はこちらにします.

v0 = 10
g = 9.8
theta = np.pi/3
t_beg = 0
t_end = 2.5
t = np.arange(t_beg, t_end, 0.1)

初期条件です.

初速$v_0$は$10\,\mathrm{m/s}$,重力加速度$g$は$9.8\,\mathrm{m/s^2}$,投げ上げる角度$\theta$は$\pi/3$とします.

また,時間$t$は$0\,\mathrm{s}$から$2.5\,\mathrm{s}$までとし,アニメーションは$0.1\,\mathrm{s}$ごとに描画します.

fig, ax = plt.subplots(figsize=(8, 4))
fig.tight_layout()
ax.set_aspect("equal")
ax.set_xlim(0, 12)
ax.set_ylim(-0.3, 5)
artists = []
for i, ti in enumerate(t):
    x = v0*np.cos(theta)*ti
    y = v0*np.sin(theta)*ti-0.5*g*ti**2
    if y <= 0.2:
        y = 0.2
    ball = patches.Circle(
        xy=(x,y), 
        radius=0.2, 
        facecolor="b", 
        edgecolor="w")
    container_ball = ax.add_patch(ball)
    ground = patches.Rectangle(
        xy=(-1, -10),
        width=13,
        height=10,
        facecolor=(0.8,0.8,0.8),
        edgecolor=(0.8,0.8,0.8),
        linewidth=1,
        linestyle=None,
    )
    container_ground = ax.add_patch(ground)
    artists.append([container_ball, container_ground])

for文より上はグラフの設定です.

球はpatches.Circleで描画しており,球の大きさは半径$0.2\,\mathrm{m}$としています.

if文では球が地面を通過しないための処理をしており,地面に接触した後転がるようになっています.

変数groundは地面を灰色で描画するためのものです.

anim = ArtistAnimation(fig, artists, interval=100)
anim.save("parabolic.gif", writer="pillow")

最後に保存をします.

今回はgif画像で保存しますが,FFmpegをインストールすればmp4での保存も可能です.